package com.example.dmweb.chat;

import com.alibaba.fastjson.JSON;
import com.example.dmcommom.ResponseResult;
import com.example.dmcommom.UserLoginToken;
import com.example.dmdomain.*;
import com.example.dmdomain.entity.*;
import com.example.dmservice.exceloutput.service.UserService;
import com.example.dmweb.chat.chatService.*;
import com.example.dmweb.chat.model.GetSystemSessionCommand;
import com.example.dmweb.chat.model.SystemSessionDeleteCommand;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.persistence.criteria.Order;
import javax.persistence.criteria.Predicate;
import javax.servlet.http.HttpServletRequest;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import static com.example.dmweb.chat.chatService.ChatGPTFileService.getFileType;

@Slf4j
@RestController
@RequestMapping("/fileUpload")
@CrossOrigin
@Api(value = "文件上传", tags = {"文件上传"})
public class ChatFileController {
    @Resource
    private ChatGPTFileService chatGPTFileService;
    @Resource
    private ChatSessionRepository chatSessionRepository;
    @Resource
    private ChatContextRepository chatContextRepository;
    @Resource
    private UserRepository userRepository;
    @Autowired
    private UserService userService;
    @Resource
    private ChatFileRepository chatFileRepository;
    @Resource
    private SystemChatFileRepository systemChatFileRepository;
    @Resource
    private SystemChatSessionRepository systemChatSessionRepository;
    @Resource
    private SystemChatContextRepository systemChatContextRepository;

    @ApiOperation("文件上传")
    @UserLoginToken
    @RequestMapping(value = "/fileUpload", method = {RequestMethod.POST})
    public ResponseResult<FileUploadResponse> fileUpload(@RequestParam MultipartFile file,@RequestParam String systemName,HttpServletRequest request) {
        try {
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            String userId = request.getHeader("Authorization");
            User user = userRepository.findUsersByUserID(userId);
            if (user == null) {
                return ResponseResult.error(401,"用户权限校验失败");
            }
            log.info("保存文件");
            String saveInfo = chatGPTFileService.saveFile(file,user.getPhone());
            log.info("文件信息入库");

            FileUploadResponse fileUploadResponse = chatGPTFileService.fileInfoWarehousing(file,user.getPhone(), userId,systemName);
            if (fileUploadResponse.getFileType().equals("未知类型文件")) {
                return ResponseResult.error("文件类型不支持");
            }
            if(Integer.parseInt(fileUploadResponse.getFileSize().replaceAll("[^0-9]", "")) < 7168) {
                return ResponseResult.success(fileUploadResponse);

            } else {
                return ResponseResult.error(400,"文件大于7MB",fileUploadResponse);
            }
        }catch (Exception e){
            e.printStackTrace();
            return ResponseResult.error("文件上传失败");
        }
    }
    @ApiOperation("会话删除")
    @UserLoginToken
    @RequestMapping(value = "/sessionDelete", method = {RequestMethod.POST})
    public ResponseResult<FileUploadResponse> fileDelete(@RequestParam("sessionId") String sessionId) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        String userId = request.getHeader("Authorization");
        User user = userRepository.findUsersByUserID(userId);
        if (user == null) {
            return ResponseResult.error(401,"用户权限校验失败");
        }
        List<ChatSession> sessionList = chatSessionRepository.findAllBySessionId(sessionId);
        sessionList.forEach(v -> v.setDelState(1));
        chatSessionRepository.saveAll(sessionList);
        return ResponseResult.success();
    }

    @ApiOperation("获取会话列表")
    @UserLoginToken
    @RequestMapping(value = "/getSessionList", method = {RequestMethod.POST})
    public ResponseResult<List<SessionListResponse>> getSessionList() {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        String userId = request.getHeader("Authorization");
//        String openId = request.getHeader("Authorization");
        User user = userRepository.findUsersByUserID(userId);
        if (user == null) {
            return ResponseResult.error(401,"用户权限校验失败");
        }

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        sdf.setTimeZone(TimeZone.getTimeZone("GMT+8"));

        Date oneDayAgo = getDateWithOffset(0);
        Date twentyNineDaysAgo = getDateWithOffset(-29);

        List<SessionListResponse> sessionListResponseList = Arrays.asList(
                new SessionListResponse(0, new ArrayList<>()),
                new SessionListResponse(1, new ArrayList<>()),
                new SessionListResponse(2, new ArrayList<>())
        );

        List<ChatSession> sessionList = chatSessionRepository.findAllByUserId(userId);

        sessionList.stream()
                .collect(Collectors.groupingBy(ChatSession::getSessionId,
                        Collectors.minBy(Comparator.comparing(ChatSession::getSessionTime))))
                .values().stream()
                .map(Optional::get)
                .forEach(s -> {
                    Date sessionTime = s.getSessionTime();
                    Map<String, String> map = new HashMap<>();
                    map.put("sessionId", s.getSessionId());
                    map.put("title", s.getSessionName());
                    map.put("sessionTime", String.valueOf(s.getSessionTime()));

                    if (sessionTime.after(oneDayAgo)) {
                        sessionListResponseList.get(0).getSessionContent().add(map);
                    } else if (sessionTime.after(twentyNineDaysAgo)) {
                        sessionListResponseList.get(1).getSessionContent().add(map);
                    } else {
                        sessionListResponseList.get(2).getSessionContent().add(map);
                    }
                });
        Comparator<Map<String, String>> sessionTimeComparator = Comparator.comparing(m -> {
            DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
            try {
                Date sessionTime = dateFormat.parse(m.get("sessionTime"));
                return sessionTime.getTime();
            } catch (ParseException e) {
                e.printStackTrace();
                return Long.MAX_VALUE;
            }
        });

        for (SessionListResponse sessionListResponse : sessionListResponseList) {
            List<Map<String, String>> sessionContent = sessionListResponse.getSessionContent();
            sessionContent.sort(sessionTimeComparator.reversed());
        }
        return ResponseResult.success(sessionListResponseList);
    }

    @ApiOperation("查找对话详情")
    @UserLoginToken
    @RequestMapping(value = "/getSessionDetails", method = {RequestMethod.POST})
    public ResponseResult<List<SessionDetailsResponse>> getSessionDetails(@RequestParam("sessionId") String sessionId) {
        try {
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = attributes.getRequest();
            String userId = request.getHeader("Authorization");
            User user = userRepository.findUsersByUserID(userId);
            if (user == null) {
                return ResponseResult.error(401,"用户权限校验失败");
            }
            //查找chat_context表
            List<String> chatSessions = chatSessionRepository.findAllBySessionId(sessionId).stream().filter(v -> v.getDelState() == 0 || v.getDelState() == 3)
                    .map(ChatSession::getRequestId).collect(Collectors.toList());
            Specification<ChatContext> spec = (root, criteriaQuery, cb) -> {
                List<Predicate> predicates = new ArrayList<>();
                predicates.add(cb.in(root.get("requestId")).value(chatSessions));
                Order order = cb.asc(root.get("sessionTime"));
                criteriaQuery.orderBy(order);
                criteriaQuery.where(cb.and(predicates.toArray(new Predicate[0])));
                return criteriaQuery.getRestriction();
            };
            List<ChatContext> chatContextList = chatContextRepository.findAll(spec);
            List<SessionDetailsResponse> sdResponseList = new ArrayList<>();
            if (chatContextList != null && chatContextList.size() > 0) {
                for (ChatContext v : chatContextList) {
                    boolean tt = false;
                    SessionDetailContent useContent = new SessionDetailContent();
                    useContent.setContent(v.getSueContent());
                    if(v.getFileIid()!= null && !v.getFileIid().isEmpty()) {
                        Specification<ChatFile> spec1 = (root, criteriaQuery, cb) -> {
                            List<Predicate> predicates = new ArrayList<>();
                            predicates.add(cb.in(root.get("fileId")).value(Arrays.asList(v.getFileIid().split(","))));
                            criteriaQuery.where(cb.and(predicates.toArray(new Predicate[0])));
                            return criteriaQuery.getRestriction();
                        };
                        List<Map<String, String>> fis = new ArrayList<>();
                        chatFileRepository.findAll(spec1).forEach(fs -> {
                            String fileExtension;
                            if (fs.getFileName().lastIndexOf(".") != -1 && fs.getFileName().lastIndexOf(".") != 0) {
                                fileExtension = fs.getFileName().substring(fs.getFileName().lastIndexOf(".")+1);
                            } else {
                                fileExtension = "未知";
                            }

                            Map<String,String> map = new HashMap<>();
                            map.put("fileId",fs.getFileId());
                            map.put("fileName",fs.getFileName());
                            map.put("fileType",getFileType(fileExtension));
                            map.put("fileSize",Integer.valueOf(fs.getFileSize())/1024 + "kb");
                            fis.add(map);
                        });
                        useContent.setFileList(fis);
                    }
                    SessionDetailContent sysContent = new SessionDetailContent();
                    sysContent.setContent(v.getSysContent());
                    for (SessionDetailsResponse sd : sdResponseList) {
                        if (sd.getRequestId().equals(v.getRequestId()) && sd.getRole().equals("user")) {
                            sd.getContentList().add(useContent);
                            tt = true;
                        }
                    }
                    if (tt) {
                        continue;
                    }
                    SessionDetailsResponse useResponse = new SessionDetailsResponse();
                    useResponse.setRole("user");
                    useResponse.setContentList(new ArrayList<>(Arrays.asList(useContent)));
                    useResponse.setRequestId(v.getRequestId());
                    sdResponseList.add(useResponse);
                    SessionDetailsResponse sysResponse = new SessionDetailsResponse();
                    sysResponse.setRole("assistant");
                    sysResponse.setRequestId(v.getRequestId());
                    sysResponse.setContentList(new ArrayList<>(Arrays.asList(sysContent)));
                    sdResponseList.add(sysResponse);
                }
            }
            return ResponseResult.success(sdResponseList);
        }catch (Exception e){
            e.printStackTrace();
            return ResponseResult.error("查找失败");
        }
    }

    @ApiOperation("获取应用会话列表")
    @UserLoginToken
    @RequestMapping(value = "/getSystemSessionList", method = {RequestMethod.POST})
    public ResponseResult<List<SessionListResponse>> getSystemSessionList(@RequestBody GetSystemSessionCommand command) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        String userId = request.getHeader("Authorization");
//        String openId = request.getHeader("Authorization");
        User user = userRepository.findUsersByUserID(userId);
        if (user == null) {
            return ResponseResult.error(401,"用户权限校验失败");
        }

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        sdf.setTimeZone(TimeZone.getTimeZone("GMT+8"));

        Date oneDayAgo = getDateWithOffset(0);
        Date twentyNineDaysAgo = getDateWithOffset(-29);

        List<SessionListResponse> sessionListResponseList = Arrays.asList(
                new SessionListResponse(0, new ArrayList<>()),
                new SessionListResponse(1, new ArrayList<>()),
                new SessionListResponse(2, new ArrayList<>())
        );

        List<SystemChatSession> sessionList = systemChatSessionRepository.findAllByUserId(userId,command.getSystemName());

        sessionList.stream()
                .collect(Collectors.groupingBy(SystemChatSession::getSessionId,
                        Collectors.minBy(Comparator.comparing(SystemChatSession::getSessionTime))))
                .values().stream()
                .map(Optional::get)
                .forEach(s -> {
                    Date sessionTime = s.getSessionTime();
                    Map<String, String> map = new HashMap<>();
                    map.put("sessionId", s.getSessionId());
                    map.put("title", s.getSessionName());
                    map.put("sessionTime", String.valueOf(s.getSessionTime()));

                    if (sessionTime.after(oneDayAgo)) {
                        sessionListResponseList.get(0).getSessionContent().add(map);
                    } else if (sessionTime.after(twentyNineDaysAgo)) {
                        sessionListResponseList.get(1).getSessionContent().add(map);
                    } else {
                        sessionListResponseList.get(2).getSessionContent().add(map);
                    }
                });
        Comparator<Map<String, String>> sessionTimeComparator = Comparator.comparing(m -> {
            DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
            try {
                Date sessionTime = dateFormat.parse(m.get("sessionTime"));
                return sessionTime.getTime();
            } catch (ParseException e) {
                e.printStackTrace();
                return Long.MAX_VALUE;
            }
        });

        for (SessionListResponse sessionListResponse : sessionListResponseList) {
            List<Map<String, String>> sessionContent = sessionListResponse.getSessionContent();
            sessionContent.sort(sessionTimeComparator.reversed());
        }
        return ResponseResult.success(sessionListResponseList);
    }

    @ApiOperation("查找应用对话详情")
    @UserLoginToken
    @RequestMapping(value = "/getSystemSessionDetails", method = {RequestMethod.POST})
    public ResponseResult<List<SessionDetailsResponse>> getSystemSessionDetails(@RequestBody GetSystemSessionCommand command) {
        try {
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = attributes.getRequest();
            String userId = request.getHeader("Authorization");
            User user = userRepository.findUsersByUserID(userId);
            if (user == null) {
                return ResponseResult.error(401,"用户权限校验失败");
            }
            //查找chat_context表
            List<String> chatSessions = systemChatSessionRepository.findAllBySessionId(command.getSessionId(), command.getSystemName()).stream().filter(v -> v.getDelState() == 0 || v.getDelState() == 3)
                    .map(SystemChatSession::getRequestId).collect(Collectors.toList());
            Specification<SystemChatContext> spec = (root, criteriaQuery, cb) -> {
                List<Predicate> predicates = new ArrayList<>();
                predicates.add(cb.in(root.get("requestId")).value(chatSessions));
                Order order = cb.asc(root.get("sessionTime"));
                criteriaQuery.orderBy(order);
                criteriaQuery.where(cb.and(predicates.toArray(new Predicate[0])));
                return criteriaQuery.getRestriction();
            };
            List<SystemChatContext> chatContextList = systemChatContextRepository.findAll(spec);
            List<SessionDetailsResponse> sdResponseList = new ArrayList<>();
            if (chatContextList != null && chatContextList.size() > 0) {
                for (SystemChatContext v : chatContextList) {
                    boolean tt = false;
                    SessionDetailContent useContent = new SessionDetailContent();
                    useContent.setContent(v.getSueContent());
                    if(v.getFileIid()!= null && !v.getFileIid().isEmpty()) {
                        Specification<SystemChatFile> spec1 = (root, criteriaQuery, cb) -> {
                            List<Predicate> predicates = new ArrayList<>();
                            predicates.add(cb.in(root.get("fileId")).value(Arrays.asList(v.getFileIid().split(","))));
                            criteriaQuery.where(cb.and(predicates.toArray(new Predicate[0])));
                            return criteriaQuery.getRestriction();
                        };
                        List<Map<String, String>> fis = new ArrayList<>();
                        systemChatFileRepository.findAll(spec1).forEach(fs -> {
                            String fileExtension;
                            if (fs.getFileName().lastIndexOf(".") != -1 && fs.getFileName().lastIndexOf(".") != 0) {
                                fileExtension = fs.getFileName().substring(fs.getFileName().lastIndexOf(".")+1);
                            } else {
                                fileExtension = "未知";
                            }

                            Map<String,String> map = new HashMap<>();
                            map.put("fileId",fs.getFileId());
                            map.put("fileName",fs.getFileName());
                            map.put("fileType",getFileType(fileExtension));
                            map.put("fileSize",Integer.valueOf(fs.getFileSize())/1024 + "KB");
                            fis.add(map);
                        });
                        useContent.setFileList(fis);
                    }
                    SessionDetailContent sysContent = new SessionDetailContent();
                    sysContent.setContent(v.getSysContent());
                    for (SessionDetailsResponse sd : sdResponseList) {
                        if (sd.getRequestId().equals(v.getRequestId()) && sd.getRole().equals("user")) {
                            sd.getContentList().add(useContent);
                            tt = true;
                        }
                    }
                    if (tt) {
                        continue;
                    }
                    SessionDetailsResponse useResponse = new SessionDetailsResponse();
                    useResponse.setRole("user");
                    useResponse.setContentList(new ArrayList<>(Arrays.asList(useContent)));
                    useResponse.setRequestId(v.getRequestId());
                    sdResponseList.add(useResponse);
                    SessionDetailsResponse sysResponse = new SessionDetailsResponse();
                    sysResponse.setRole("assistant");
                    sysResponse.setRequestId(v.getRequestId());
                    sysResponse.setContentList(new ArrayList<>(Arrays.asList(sysContent)));
                    sdResponseList.add(sysResponse);
                }
            }
            return ResponseResult.success(sdResponseList);
        }catch (Exception e){
            e.printStackTrace();
            return ResponseResult.error("查找失败");
        }
    }

    @ApiOperation("应用会话删除")
    @UserLoginToken
    @RequestMapping(value = "/systemSessionDelete", method = {RequestMethod.POST})
    public ResponseResult<FileUploadResponse> systemSessionDelete(@RequestBody SystemSessionDeleteCommand command) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        String userId = request.getHeader("Authorization");
        User user = userRepository.findUsersByUserID(userId);
        if (user == null) {
            return ResponseResult.error(401,"用户权限校验失败");
        }
        List<SystemChatSession> sessionList = systemChatSessionRepository.findAllBySessionId(command.getSessionId(), command.getSystemName());
        sessionList.forEach(v -> v.setDelState(1));
        systemChatSessionRepository.saveAll(sessionList);
        return ResponseResult.success();
    }


    private Date getDateWithOffset(int daysOffset) {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DAY_OF_MONTH, daysOffset);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }
}
